﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MyIEnumerable myienumerable=new MyIEnumerable(new string[] { "1111","2222"});

            var t = myienumerable.GetEnumerator();
            while (t.MoveNext())
            {
                Console.WriteLine(t.Current);
            }
            
            Console.Read();
        }

        public static T RandomEnumerableValue<T>(this IEnumerable<T> source, Random random)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (random == null)
                throw new ArgumentNullException("random");
            if (source is ICollection)
            {
                ICollection collection = source as ICollection;
                int count = collection.Count;
                if (count == 0)
                    throw new Exception("IEnumerable没有数据");
                return source.ElementAt(random.Next(count));
            }
            using (var iterator = source.GetEnumerator())
            {
                if (!iterator.MoveNext())
                {
                    throw new Exception("IEnumerable没有数据");
                }
                int count = 1;
                T current = iterator.Current;
                while (iterator.MoveNext())
                {
                    count++;
                    if (random.Next(count) == 0)
                        current = iterator.Current;
                }
                return current;
            }
        }

        public void lambda()
        {
            Func<Student, bool> func = t => t.Name == "农码一生" && t.Address == "1";
            Expression<Func<Student, bool>> expression = t => t.Name == "农码一生" && t.Sex == "3";
            AnalysisExpression.VisitExpression(expression);
            var f = expression.Compile();
            MyQueryable<Student> c = new MyQueryable<Student>();

            c.Where(s => s.Name == "");
            var list = new List<Student>();
            list.Add(new Student() { Name = "农码一生", Sex = "1" });
            list.Add(new Student() { Name = "农生", Sex = "2" });
            list.Add(new Student() { Name = "生", Sex = "3" });
            list.Add(new Student() { Name = "农码一生", Sex = "5" });


            var q = list.Where(func);
            foreach (var item in q)
            {
                Console.WriteLine(item.ToString());
            }
            Console.ReadLine();


            q = list.Where(func);
            foreach (var item in q)
            {
                Console.WriteLine(item.ToString());
            }
            Console.ReadLine();
        }

        //表达式解析
        public static class AnalysisExpression
        {
            public static void VisitExpression(Expression expression)
            {
                switch (expression.NodeType)
                {
                    case ExpressionType.Call://执行方法
                        MethodCallExpression method = expression as MethodCallExpression;
                        Console.WriteLine("方法名:" + method.Method.Name);
                        for (int i = 0; i < method.Arguments.Count; i++)
                            VisitExpression(method.Arguments[i]);
                        break;
                    case ExpressionType.Lambda://lambda表达式
                        LambdaExpression lambda = expression as LambdaExpression;
                        VisitExpression(lambda.Body);
                        break;
                    case ExpressionType.Equal://相等比较
                    case ExpressionType.AndAlso://and条件运算
                        BinaryExpression binary = expression as BinaryExpression;
                        Console.WriteLine("运算符:" + expression.NodeType.ToString());
                        VisitExpression(binary.Left);
                        VisitExpression(binary.Right);
                        break;
                    case ExpressionType.Constant://常量值
                        ConstantExpression constant = expression as ConstantExpression;
                        Console.WriteLine("常量值:" + constant.Value.ToString());
                        break;
                    case ExpressionType.MemberAccess:
                        MemberExpression Member = expression as MemberExpression;
                        Console.WriteLine("字段名称:{0}，类型:{1}", Member.Member.Name, Member.Type.ToString());
                        break;
                    default:
                        Console.Write("UnKnow");
                        break;
                }
            }

        }
    }
    public class Student
    {
        public string Name { get; set; }

        public int Age { get; set; }

        public string Address { get; set; }

        public string Sex { get; set; }

        public override string ToString()
        {
            return this.Name+this.Age+this.Address+this.Sex;
        }
    }

    public class MyQueryProvider : IQueryProvider
    {
        public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
        {
            return new MyQueryable<TElement>(expression);
        }

        public IQueryable CreateQuery(Expression expression)
        {
            throw new NotImplementedException();
        }

        public TResult Execute<TResult>(Expression expression)
        {
            return default(TResult);
        }

        public object Execute(Expression expression)
        {
            return new List<object>();
        }
    }
    public class MyQueryable<T> : IQueryable<T>
    {
        public MyQueryable()
        {
            _provider = new MyQueryProvider();
            _expression = Expression.Constant(this);
        }

        public MyQueryable(Expression expression)
        {
            _provider = new MyQueryProvider();
            _expression = expression;
        }
        public Type ElementType
        {
            get { return typeof(T); }
        }

        private Expression _expression;
        public Expression Expression
        {
            get { return _expression; }
        }

        private IQueryProvider _provider;
        public IQueryProvider Provider
        {
            get { return _provider; }
        }

        public IEnumerator GetEnumerator()
        {
            return (Provider.Execute(Expression) as IEnumerable).GetEnumerator();
        }

        IEnumerator<T> IEnumerable<T>.GetEnumerator()
        {
            var result = _provider.Execute<List<T>>(_expression);
            if (result == null)
                yield break;
            foreach (var item in result)
            {
                yield return item;
            }
        }
    }
}
